# vcg graph language lexer+parser to use with packcc parser generator

%prefix "vcg"

%source{

#include <stdio.h>

static int nlines = 1;

static int debug = 0;

static const char *dbg_str[] = { "Evaluating rule", "Matched rule", "Abandoning rule" };

#define PCC_DEBUG(event, rule, level, pos, buffer, length) \
    if (debug) { fprintf(stdout, "%*s%s %s @%d [%.*s]\n", (int)(level * 2), "", dbg_str[event], rule, (int)pos, (int)length,  buffer); fflush(stdout); }

    /* NOTE: To guarantee the output order, stderr, which can lead a race condition with stdout, is not used. */

}

# start of input
file	<- _ graph _ !.

graph	<-  'graph' _ ':' _ '{' _ graph_entry_list _ '}'

graph_entry_list	<-  graph_entry*

graph_entry	<- graph_attribute _
	/ graph _
	/ node _
	/ edge _
	/ nearedge _
	/ bentnearedge _
	/ backedge _
	/ constraint _
	/ node_defaults _
	/ edge_defaults _
	/ foldnode_defaults _
	/ foldedge_defaults _

graph_attribute	<- 'title' _ ':' _ str_const
	/ 'label' _ ':' _ str_const
	/ 'info1' _ ':' _ str_const
	/ 'info2' _ ':' _ str_const
	/ 'info3'_  ':' _ str_const
	/ 'color' _ ':' _ enum_color
	/ 'text_color' _ ':' _ enum_color
	/ 'textcolor' _ ':' _ enum_color
	/ 'border_color' _ ':' _ enum_color
	/ 'bordercolor' _ ':' _ enum_color
	/ 'width' _ ':' _ int_const
	/ 'height' _ ':' _ int_const
	/ 'border_width' _ ':' _ int_const
	/ 'borderwidth' _ ':' _ int_const
	/ 'x' _ ':' _ int_const
	/ 'y' _ ':' _ int_const
	/ 'loc' _ ':' _ '{' _ 'x' _ ':' _ int_const _ 'y' _ ':' _ int_const _ '}'
	/ 'folding' _ ':' _ int_const
	/ 'scaling' _ ':' _ float_const
	/ 'shrink' _ ':' _ int_const
	/ 'stretch' _ ':' _ int_const
	/ 'text_mode' _ ':' _ enum_textmode
	/ 'textmode' _ ':' _ enum_textmode
	/ 'shape' _ ':' _ enum_shape
	/ 'level' _ ':' _ int_const
	/ 'verticalorder' _ ':' _ int_const
	/ 'vertical_order' _ ':' _ int_const
	/ 'horizontalorder' _ ':' _ int_const
	/ 'horizontal_order' _ ':' _ int_const
	/ 'status' _ ':' _ enum_status
	/ 'xmax' _ ':' _ int_const
	/ 'ymax' _ ':' _ int_const
	/ 'xbase' _ ':' _ int_const
	/ 'ybase' _ ':' _ int_const
	/ 'xspace' _ ':' _ int_const
	/ 'xlspace' _ ':' _ int_const
	/ 'yspace' _ ':' _ int_const
	/ 'xraster' _ ':' _ int_const
	/ 'xlraster' _ ':' _ int_const
	/ 'yraster' _ ':' _ int_const
	/ 'invisible' _ ':' _ int_const
	/ 'hidden' _ ':' _ int_const
	/ 'classname' _ int_const _ ':' _ str_const
	/ 'class_name' _ int_const _ ':' _ str_const
	/ 'infoname' _ int_const _ ':' _ str_const
	/ 'colorentry' _ int_const _ ':' _ int_const _ int_const _ int_const
	/ 'color_entry' _ int_const _ ':' _ int_const _ int_const _ int_const
	/ 'layoutalgorithm' _ ':' _ enum_layoutalgorithm
	/ 'layout_algorithm' _ ':' _ enum_layoutalgorithm
	/ 'layoutfrequency' _ ':' _ enum_layoutfrequency
	/ 'layout_frequency' _ ':' _ enum_layoutfrequency
	/ 'layoutdownfactor' _ ':' _ int_const
	/ 'layoutupfactor' _ ':' _ int_const
	/ 'layout_upfactor' _ ':' _ int_const
	/ 'layoutnearfactor' _ ':' _ int_const
	/ 'layout_nearfactor' _ ':' _ int_const
	/ 'layoutsplinefactor' _ ':' _ int_const
	/ 'layout_splinefactor' _ ':' _ int_const
	/ 'lateedgelabels' _ ':' _ enum_yes_no
	/ 'late_edge_labels' _ ':' _ enum_yes_no
	/ 'displayedgelabels' _ ':' _ enum_yes_no
	/ 'display_edge_labels' _ ':' _ enum_yes_no
	/ 'dirtyedgelabels' _ ':' _ enum_yes_no
	/ 'dirty_edge_labels' _ ':' _ enum_yes_no
	/ 'finetuning' _ ':' _ enum_yes_no
	/ 'fine_tuning' _ ':' _ enum_yes_no
	/ 'hidesingles' _ ':' _ enum_yes_no
	/ 'hide_singles' _ ':' _ enum_yes_no
	/ 'straightphase' _ ':' _ enum_yes_no
	/ 'straight_phase' _ ':' _ enum_yes_no
	/ 'priorityphase' _ ':' _ enum_yes_no
	/ 'priority_phase' _ ':' _ enum_yes_no
	/ 'manhattenedges' _ ':' _ enum_yes_no
	/ 'manhatten_edges' _ ':' _ enum_yes_no
	/ 'manhattanedges' _ ':' _ enum_yes_no
	/ 'manhattan_edges' _ ':' _ enum_yes_no
	/ 'smanhattenedges' _ ':' _ enum_yes_no
	/ 'smanhatten_edges' _ ':' _ enum_yes_no
	/ 'smanhattanedges' _ ':' _ enum_yes_no
	/ 'smanhattan_edges' _ ':' _ enum_yes_no
	/ 'nonearedges'
	/ 'no_nearedges'
	/ 'no_near_edges'
	/ 'nearedges' _ ':' _ enum_yes_no
	/ 'near_edges' _ ':' _ enum_yes_no
	/ 'orientation' _ ':' _ enum_orientation
	/ 'nodealignment' _ ':' _ enum_node_align
	/ 'node_alignment' _ ':' _ enum_node_align
	/ 'portsharing' _ ':' _ enum_yes_no
	/ 'port_sharing' _ ':' _ enum_yes_no
	/ 'arrowmode' _ ':' _ enum_arrow_mode
	/ 'arrow_mode' _ ':' _ enum_arrow_mode
	/ 'spreadlevel' _ ':' _ int_const
	/ 'spread_level' _ ':' _ int_const
	/ 'treefactor' _ ':' _ float_const
	/ 'tree_factor' _ ':' _ float_const
	/ 'crossingphase2' _ ':' _ enum_yes_no
	/ 'crossing_phase2' _ ':' _ enum_yes_no
	/ 'crossingoptimization' _ ':' _ enum_yes_no
	/ 'crossing_optimization' _ ':' _ enum_yes_no
	/ 'crossingweight' _ ':' _ enum_cross_weight
	/ 'crossing_weight' _ ':' _ enum_cross_weight
	/ 'view' _ ':' _ enum_view
	/ 'edges' _ ':' _ enum_yes_no
	/ 'nodes' _ ':' _ enum_yes_no
	/ 'splines' _ ':' _ enum_yes_no
	/ 'bmax' _ ':' _ int_const
	/ 'cmax' _ ':' _ int_const
	/ 'cmin' _ ':' _ int_const
	/ 'pmax' _ ':' _ int_const
	/ 'pmin' _ ':' _ int_const
	/ 'rmax' _ ':' _ int_const
	/ 'rmin' _ ':' _ int_const
	/ 'smax' _ ':' _ int_const
	/ 'typename' _ ':' _ str_const
	/ 'type_name' _ ':' _ str_const
	/ 'include' _ ':' _ str_const
	/ 'layoutparameter' _ ':' _ array_value
	/ 'layout_parameter' _ ':' _ array_value
	/ 'topsort' _ ':' _ enum_topsort
	/ 'top_sort' _ ':' _ enum_topsort
	/ 'inputfunction' _ ':' _ str_const
	/ 'input_function' _ ':' _ str_const
	/ 'outputfunction' _ ':' _ str_const
	/ 'output_function' _ ':' _ str_const
	/ 'xscrollbar' _ ':' _ int_const
	/ 'yscrollbar' _ ':' _ int_const

enum_color	<- 'aquamarine'
	/ 'black'
	/ 'blue'
	/ 'cyan'
	/ 'darkblue'
	/ 'darkcyan'
	/ 'darkgreen'
	/ 'darkgray'
	/ 'darkgrey'
	/ 'darkmagenta'
	/ 'darkred'
	/ 'darkyellow'
	/ 'gold'
	/ 'green'
	/ 'khaki'
	/ 'lightblue'
	/ 'lightcyan'
	/ 'lightgreen'
	/ 'lightgray'
	/ 'lightgrey'
	/ 'lightmagenta'
	/ 'lightred'
	/ 'lightyellow'
	/ 'lilac'
	/ 'magenta'
	/ 'orange'
	/ 'orchid'
	/ 'pink'
	/ 'purple'
	/ 'red'
	/ 'turquoise'
	/ 'white'
	/ 'yellow'
	/ int_const

enum_topsort	<- 'high'
	/ 'low'

enum_orientation	<- 'toptobottom'
	/ 'top_to_bottom'
	/ 'bottomtotop'
	/ 'bottom_to_top'
	/ 'lefttoright'
	/ 'left_to_right'
	/ 'righttoleft'
	/ 'right_to_left'

enum_layoutalgorithm	<- 'barycenter'
	/ 'bary_center'
	/ 'isi'
	/ 'planar'
	/ 'constraints'
	/ 'tree'
	/ 'maxdepth'
	/ 'mindepth'
	/ 'maxdepthslow'
	/ 'mindepthslow'
	/ 'maxdegree'
	/ 'mindegree'
	/ 'maxindegree'
	/ 'minindegree'
	/ 'maxoutdegree'
	/ 'minoutdegree'
	/ 'minbackward'
	/ 'dfs'

enum_layoutfrequency	<- 'every'
	/ 'manual'

enum_status 	<- 'black'
	/ 'grey'
	/ 'gray'
	/ 'white'

enum_yes_no	<- 'yes'
	/ 'no'

enum_cross_weight	<- 'bary'
	/ 'median'
	/ 'barymedian'
	/ 'medianbary'

enum_view	<- 'cfish'
	/ 'fcfish'
	/ 'pfish'
	/ 'fpfish'

enum_arrow_mode	<- 'fixed'
	/ 'free'

foldnode_defaults	<- 'foldnode' _ '.' _ node_attribute+
	/ 'fold_node' _ '.' _ node_attribute+

foldedge_defaults	<- 'foldedge' _ '.' _ edge_attribute+
	/ 'fold_edge' _ '.' _ edge_attribute+

node_defaults	<- 'node' _ '.' _ node_attribute+

edge_defaults	<- 'edge' _ '.' _ edge_attribute+

node	<- 'node' ':' _ '{' _ node_attribute_list _ '}'

node_attribute_list	<- node_attribute+

edge	<- 'edge' _ ':' _ '{' _ edge_attribute_list _ '}'

nearedge	<- 'nearedge' _ ':' _ '{' _ edge_attribute_list _ '}'
	/ 'near_edge' _ ':' _ '{' _ edge_attribute_list _ '}'

bentnearedge	<- 'bentnearedge' _ ':' _ '{' _ edge_attribute_list _ '}'
	/ 'bent_nearedge' _ ':' _ '{' _ edge_attribute_list _ '}'
	/ 'bent_near_edge' _ ':' _ '{' _ edge_attribute_list _ '}'

backedge	<- 'backedge' _  ':' _ '{' _ edge_attribute_list _ '}'
	/ 'back_edge' _  ':' _ '{' _ edge_attribute_list _ '}'

edge_attribute_list	<- edge_attribute+

constraint	<- 'constraint' _ ':' _ '{' _ constraint_attribute_list _ '}'

constraint_attribute_list	<- constraint_attribute+

node_attribute	<- 'title' _ ':' _ str_const
	/ 'label' _ ':' _ str_const
	/ 'info1' _ ':' _ str_const
	/ 'info2' _ ':' _ str_const
	/ 'info3' _ ':' _ str_const
	/ 'fontname' _ ':' _ str_const
	/ 'font_name' _ ':' _ str_const
	/ 'color' _ ':' _ enum_color
	/ 'textcolor' _ ':' _ enum_color
	/ 'text_color' _ ':' _ enum_color
	/ 'labelcolor' _ ':' _ enum_color
	/ 'label_color' _ ':' _ enum_color
	/ 'bordercolor' _ ':' _ enum_color
	/ 'border_color' _ ':' _ enum_color
	/ 'iconfile' _ ':' _ str_const
	/ 'icon_file' _ ':' _ str_const
	/ 'anchorpoints' _ ':' _ str_const
	/ 'anchor_points' _ ':' _ str_const
	/ 'typename' _ ':' _ str_const
	/ 'type_name' _ ':' _ str_const
	/ 'width' _ ':' _ int_const
	/ 'height' _ ':' _ int_const
	/ 'borderwidth' _ ':' _ int_const
	/ 'border_width' _ ':' _ int_const
	/ 'loc' _ ':' _ '{' _ 'x' _ ':' _ int_const _ 'y' _ ':' _ int_const _ '}'
	/ 'folding' _ ':' _ int_const
	/ 'scaling' _ ':' _ float_const
	/ 'shrink' _ ':' _ int_const
	/ 'stretch' _ ':' _ int_const
	/ 'iconwidth' _ ':' _ int_const
	/ 'icon_width' _ ':' _ int_const
	/ 'iconheight' _ ':' _ int_const
	/ 'icon_height' _ ':' _ int_const
	/ 'textmode' _ ':' _ enum_textmode
	/ 'text_mode' _ ':' _ enum_textmode
	/ 'iconstyle' _ ':' _ enum_iconstyle
	/ 'icon_style' _ ':' _ enum_iconstyle
	/ 'shape' _ ':' _ enum_shape
	/ 'level' _ ':' _ int_const
	/ 'verticalorder' _ ':' _ int_const
	/ 'vertical_order' _ ':' _ int_const
	/ 'horizontalorder' _ ':' _ int_const
	/ 'horizontal_order' _ ':' _ int_const

enum_textmode	<- 'center'
	/ 'leftjustify'
	/ 'left_justify'
	/ 'rightjustify'
	/ 'right_justify'

enum_shape	<- 'box'
	/ 'rhomb'
	/ 'ellipse'
	/ 'triangle'

enum_node_align	<- 'bottom'
	/ 'top'
	/ 'center'

enum_iconstyle	<- 'bottom'
	/ 'top'
	/ 'around'

edge_attribute	<- 'sourcename' _ ':' _ str_const
	/ 'source_name' _ ':' _ str_const
	/ 'targetname' _ ':' _ str_const
	/ 'targetname' _ ':' _ str_const
	/ 'label' _ ':' _ str_const
	/ 'textcolor' _ ':' _ enum_color
	/ 'text_color' _ ':' _ enum_color
	/ 'fontname' _ ':' _ str_const
	/ 'font_name' _ ':' _ str_const
	/ 'color' _ ':' _ enum_color
	/ 'typename' _ ':' _ str_const
	/ 'type_name' _ ':' _ str_const
	/ 'thickness' _ ':' _ int_const
	/ 'class' _ ':' _ int_const
	/ 'priority' _ ':' _ int_const
	/ 'arrowwidth' _ ':' _ int_const
	/ 'arrow_width' _ ':' _ int_const
	/ 'arrowheight' _ ':' _ int_const
	/ 'arrow_height' _ ':' _ int_const
	/ 'arrowcolor' _ ':' _ enum_color
	/ 'arrow_color' _ ':' _ enum_color
	/ 'backarrowcolor' _ ':' _ enum_color
	/ 'backarrow_color' _ ':' _ enum_color
	/ 'back_arrow_color' _ ':' _ enum_color
	/ 'arrowsize' _ ':' _ int_const
	/ 'arrow_size' _ ':' _ int_const
	/ 'backarrowsize' _ ':' _ int_const
	/ 'backarrow_size' _ ':' _ int_const
	/ 'back_arrow_size' _ ':' _ int_const
	/ 'arrowstyle' _ ':' _ enum_arrowstyle
	/ 'arrow_style' _ ':' _ enum_arrowstyle
	/ 'backarrowstyle' _ ':' _ enum_arrowstyle
	/ 'backarrow_style' _ ':' _ enum_arrowstyle
	/ 'back_arrow_style' ':' _ enum_arrowstyle
	/ 'linestyle' _ ':' _ enum_linestyle
	/ 'line_style' _ ':' _ enum_linestyle
	/ 'anchor' _ ':' _ int_const
	/ 'horizontalorder' _ ':' _ int_const
	/ 'horizontal_order' _ ':' _ int_const

enum_linestyle	<- 'continuous'
	/ 'solid'
	/ 'dotted'
	/ 'dashed'
	/ 'invisible'

enum_arrowstyle	<- 'none'
	/ 'line'
	/ 'solid'

constraint_attribute	<- 'title' _ ':' _ str_const
	/ 'priority' _ ':' _ int_const
	/ 'size' _ ':' _ int_const
	/ 'nodes' _ ':' _ '{' _ string_array _ '}'
	/ 'interval' _ ':' _ array_value
	/ 'name' _ ':' _ enum_name
	/ 'dimension' _ ':' _ enum_dimension

string_array	<- string_array _ str_const
	/ str_const

enum_name	<- 'equal'
	/ 'smaller'
	/ 'greater'
	/ 'neighbors'
	/ 'lowmargin'
	/ 'low_margin'
	/ 'highmargin'
	/ 'high_margin'
	/ 'range'
	/ 'cluster'
	/ 'limit'
	/ 'above'
	/ 'below'
	/ 'left'
	/ 'right'
	/ 'in_front'
	/ 'behind'
	/ 'equalposition'
	/ 'equal_position'
	/ 'equalrow'
	/ 'equal_row'
	/ 'equalcolumn'
	/ 'equal_column'
	/ 'topmargin'
	/ 'top_margin'
	/ 'bottommargin'
	/ 'bottom_margin'
	/ 'leftmargin'
	/ 'left_margin'
	/ 'rightmargin'
	/ 'right_margin'
	/ 'upperneighbor'
	/ 'upper_neighbor'
	/ 'lowerneighbor'
	/ 'lower_neighbor'
	/ 'leftneighbor'
	/ 'left_neighbor'
	/ 'rightneighbor'
	/ 'right_neighbor'

enum_dimension	<- 'x'
	/ 'y'
	/ 'z'

attribute_value	<- lexer_int
	/ lexer_float
	/ lexer_char
	/ lexer_string
	/ array_value

array_value	<- '{' _ index_value_list _ '}'

index_value_list	<- index_value_list _ index_value
	/ index_value

index_value	<- attribute_value
	/ index _ ':' _ attribute_value
	/ range _ ':' _ attribute_value
	/ '*' _ ':' _ attribute_value

range	<- '[' _ int_const _ '-' _ int_const ']'

index	<- lexer_int

int_const	<- lexer_int

float_const	<- lexer_float

str_const	<- lexer_string

lexer_int	<- ( ('-' / '+')? [0-9]+ _ ) _

lexer_float	<- ( ('-' / '+')? [0-9]* '.' [0-9]+ (['e''E'] ('-' / '+')? [0-9]+ )?  _ ) _

lexer_char	<- .

lexer_string	<- '"' string_char* '"' _

string_char	<-
	'\\' "\""
	/ (!"\"" .)

cppcomment	<- "//" (!endofline .)*

ccs	<- '*/'

ccomment	<- '/*' (!ccs .)* '*/'

_	<-		(space / ccomment / cppcomment)*

space	<-	(' ' / '\t' / endofline)

endofline	<-	( '\r\n' / '\n' / '\r' / '\n\r' ) { nlines++; }

%%

int main() {
    vcg_context_t *ctx = vcg_create(NULL);
    while (vcg_parse(ctx, NULL)){;}
    vcg_destroy(ctx);
    printf("/* parsed %d lines */\n",nlines);
    return 0;
}
